package cn.sycoder.controller;

import cn.afterturn.easypoi.excel.ExcelExportUtil;
import cn.afterturn.easypoi.excel.ExcelImportUtil;
import cn.afterturn.easypoi.excel.entity.ExportParams;
import cn.afterturn.easypoi.excel.entity.ImportParams;
import cn.sycoder.config.FileServiceConfig;
import cn.sycoder.constant.Const;
import cn.sycoder.dto.ProductCode;
import cn.sycoder.dto.ProductFileDto;
import cn.sycoder.entity.Product;
import cn.sycoder.exception.BusinessException;
import cn.sycoder.exception.SystemException;
import cn.sycoder.mapper.ProductHistoryMapper;
import cn.sycoder.mapper.ProductMapper;
import cn.sycoder.resp.Code;
import cn.sycoder.resp.Resp;
import cn.sycoder.service.IProductService;
import cn.sycoder.utils.*;
import com.google.zxing.WriterException;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.apache.poi.ss.usermodel.*;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.*;

import static cn.sycoder.utils.BaseDateUtils.getProductTableName;

@RestController
@RequestMapping("/api")
@Api(tags = "库存管理模块上传/下载")
@Slf4j
@Transactional(rollbackFor = Exception.class)
public class FilesController {

    @Autowired
    IProductService service;

    @Autowired
    ProductMapper mapper;

    @Value("${history.enable}")
    private Boolean historyEnable;

    @Autowired
    ProductHistoryMapper productHistoryMapper; // 入库/出库历史（分表）

    @PostMapping("/file/upload")
    @ApiOperation(value = "库存管理上传")
    public Resp upload(@RequestParam("file") MultipartFile file,// 上传单个文件
                       @RequestParam("token") String token) {

        if (file.isEmpty()) {
            return Resp.success(false, "文件为空！");
        }

        boolean ret;
        List<Product> list;
        // 解析文档需要用到 ImportParams 对象
        final ImportParams importParams = new ImportParams();
        importParams.setHeadRows(1);
        try {
            final List<ProductFileDto> products = ExcelImportUtil.importExcel(
                    file.getInputStream(),
                    ProductFileDto.class,
                    importParams
            );
//            response.put("data",products);

            // 获取当前登录用户名
            String username = JwtUtil.extractUsername(token);

            // 将文件数据拷贝到 Product 对象
            list = new ArrayList<>();
            for (ProductFileDto productFile : products) {
                Product product = Product.builder().build();
                BeanUtils.copyProperties(productFile, product);
                product.setCreateUser(username);
                product.setAlarm(Const.UN_ALARM);
                product.setLocation(productFile.getStoreHouse() + "," + productFile.getSite());
                list.add(product);
            }
            // 获取到excel列表数据进行存储数据
            ret = service.saveBatch(list); // 批量插入

        } catch (Exception e) {
            e.printStackTrace();
            throw new SystemException(Code.SYSTEM_ERR, "文件上传格式有误！");
        }
        return ret ? Resp.success(true, list) : Resp.success(false, "服务器异常！");
    }


    @PostMapping("/file/export")
    @ApiOperation(value = "库存管理导出（下载）")
    public void export(HttpServletResponse response) {

        // 获取数据
        List<ProductFileDto> list = mapper.selectProduct();
        System.out.println(list);

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        response.setContentType("application/vnd.ms-excel");
        OutputStream out = null;
        try {
            response.setHeader("Content-disposition",
                    "attachment;filename=" + URLEncoder.encode("库存导出" + sdf.format(new Date()) + ".xls"));
            Workbook workbook = ExcelExportUtil.exportExcel(new ExportParams("产品库存信息", "物资"),
                    ProductFileDto.class, list);
            out = response.getOutputStream();
            workbook.write(out);
        } catch (Exception e) {
            System.out.println(e.getMessage());
            System.out.println(e);
        } finally {
            try {
                if (out != null)
                    out.close();
            } catch (IOException e) {
            }
        }
    }


    @PostMapping("/Bar/code")
    @ApiOperation(value = "库存管理-生成条形码")
    public ResponseEntity<Map<String, String>> getBarCode(@RequestParam("code") String code) {

        // 获取产品id
        Product product = mapper.selectProductByCode(code);

        Map<String, String> response = new HashMap<>();
        if (product != null) {
            // 定义条形码内容
            String contents = product.getId() + code; // id + code
            String barCodeBase64 = "";
            try {
                barCodeBase64 = "data:image/png;base64," + BarCodeUtil.generateBarCode(contents);

            } catch (WriterException | IOException e) {
                throw new SystemException(Code.SYSTEM_ERR, "服务异常！");
            }
            // 将条形码图片的Base64编码字符串放入响应体中
            response.put("barCodeImage", barCodeBase64);

            // 生成条形码时，判断当前编号的产品库存是否为0，如果时0做出提示
            Integer sum = mapper.selectInventory(code);
            if (sum == 0) {
                response.put("msg", "000");
                // 返回包含条形码图片的JSON响应
                return new ResponseEntity<>(response, HttpStatus.OK);
            } else {
                return new ResponseEntity<>(response, HttpStatus.OK);
            }

        } else {
            response.put("msg", "查询失败！");
            return new ResponseEntity<>(response, HttpStatus.FOUND);
        }
    }


    @PostMapping("/getProductByCode")
    @ApiOperation(value = "库存管理-扫码后获取信息")
    public Resp parseQRCode(@RequestBody Map<String, String> requestBody) {

        String code = requestBody.get("code");
        // 获取产品信息
        Product product = mapper.selectProductByCode(code);
        List<ProductCode> list = new ArrayList<>();
        ProductCode productCode = new ProductCode();
        BeanUtils.copyProperties(product, productCode);
        list.add(productCode);
        return list != null ? Resp.success(true, list) : Resp.success(false, "查询失败！");
    }


    @PostMapping("/saveInventory")
    @ApiOperation(value = "库存管理入库")
    public Resp inputInventory(@RequestBody List<ProductCode> inventoryList, HttpServletRequest request) {

        // 从请求头中获取token
        String token = request.getHeader("Authorization");
        if (token!= null && token.startsWith("Bearer ")) {
            token = token.substring(7);
            System.out.println("Received token: " + token);
        } else {
            // 这里可以根据情况决定如何处理没有有效token的情况，比如返回错误信息
            System.out.println("Invalid or missing token");
        }
        // 通过token获取用户名
        String username = JwtUtil.extractUsername(token);
        int ret = 0;
        try {
            for (ProductCode product : inventoryList) {
                String name = product.getName();
                // 当前库存
                Integer inventory = product.getInventory();
                // 当前入库数量
                Integer inventorySum = product.getInventorySum();
                // 查询历史入库数量
                Integer sum = mapper.SelectInventorySum(name); // 查询历史入库总量
                Integer newInventory = inventory + inventorySum; // 更新库存总量（库存数量 + 当前入库数量）

                Integer newInventorySum = 0;
                if (sum == null) {
                    newInventorySum = inventorySum; // 更新入库历史总量（历史入库总量）
                } else {
                    newInventorySum = sum + inventorySum; // 更新入库历史总量（当前入库数量 + 历史入库总量）
                }
                ret = mapper.updateInventoryInput(name, newInventory, newInventorySum); // 更新数据库（入库操作）

                if (historyEnable){
                    // 存储入库信息（分表）
                    productHistoryMapper.insertInputOrOutputSum(name,inventorySum,Const.INPUT_SUM,
                            getProductTableName(),username,new Date());
                }

            }
        } catch (BusinessException e) {
            throw new BusinessException(Code.BUSINESS_ERR, "处理业务异常，请稍后再试！");
        }
        return ret > 0 ? Resp.success(true) : Resp.success(false, "入库失败，请稍后再试！");
    }


    @PostMapping("/removeInventory")
    @ApiOperation(value = "库存管理出库")
    public Resp outputInventory(@RequestBody List<ProductCode> inventoryList,HttpServletRequest request) {

        // 从请求头中获取token
        String token = request.getHeader("Authorization");
        if (token!= null && token.startsWith("Bearer ")) {
            token = token.substring(7);
            System.out.println("Received token: " + token);
        } else {
            // 这里可以根据情况决定如何处理没有有效token的情况，比如返回错误信息
            System.out.println("Invalid or missing token");
        }
        // 通过token获取用户名
        String username = JwtUtil.extractUsername(token);

        int ret = 0;
        try {
            for (ProductCode product : inventoryList) {
                String name = product.getName();
                // 当前库存
                Integer inventory = product.getInventory();
                // 当前出库数量
                Integer inventoryRemove = product.getInventoryRemove();
                // 查询历史入库数量
                Integer remove = mapper.SelectInventoryRemove(name); // 查询历史出库总量
                Integer newInventory = inventory - inventoryRemove; // 更新库存总量（库存数量 - 当前出库数量）

                Integer newInventoryRemove = 0;
                if (remove == null) {
                    newInventoryRemove = inventoryRemove; // 更新出库历史总量（历史出库总量）
                } else {
                    newInventoryRemove = remove + inventoryRemove; // 更新出库历史总量（当前出库数量 + 历史出库总量）
                }

                // 出库的量不能超过库存总量
                if (newInventory >= 0) {
                    ret = mapper.updateInventoryOutput(name, newInventory, newInventoryRemove); // 更新数据库（出库操作）
                } else {
                    return Resp.success(false, "当前库存不足，请重新输入！");
                }

                if (historyEnable){
                    // 存储出库信息（分表）
                    productHistoryMapper.insertInputOrOutputSum(name,inventoryRemove,Const.OUTPUT_SUM,
                            getProductTableName(),username,new Date());
                }
            }
        } catch (BusinessException e) {
            throw new BusinessException(Code.BUSINESS_ERR, "处理业务异常，请稍后再试！");
        }
        return ret > 0 ? Resp.success(true) : Resp.success(false, "出库失败，请稍后再试！");
    }



    @PostMapping("/file/uploadImage")
    @ApiOperation(value = "文件上传 .txt")
    public Resp updateFile(@RequestParam("files") MultipartFile file) {

        String fileName = null;
        try {
            if (!file.isEmpty()) {
                fileName = FileUploadUtils.uploadText(FileServiceConfig.getUploadPath(), file);
                System.out.println("fileName:" + fileName);
            }
            return Resp.success(true,fileName);
        } catch (Exception e) {
            return Resp.success(false);
        }
    }


    @PostMapping("/upload/avatar")
    @ApiOperation(value = "图片上传 .png")
    public Resp updateAvatar(@RequestParam("file") MultipartFile file,@RequestParam("code") String code) {

        try {
            if (!file.isEmpty()) {
                String avatar = FileUploadUtils.uploadPicture(FileServiceConfig.getAvatarPath(), file);
                String url = "http://localhost:8080/api/noLogin/readImageFile?url=D:/2024-Java/SpringBoot-Project/homework/springboot-project/src/main/resourcesavatar/" + avatar;
                mapper.updateUrl(url,code);
                System.out.println(url);

                return Resp.success(true,url); // 返回前端
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return Resp.success(false,"上传失败！");
    }


    @RequestMapping(value = "/noLogin/readImageFile",method =RequestMethod.GET)
    @ApiOperation(value = "图片查看")
    public Resp getUrlFile(@RequestParam(value = "url",required = true) String url, HttpServletResponse response) {
        System.out.println(url);
        File file = new File(url);
        // 后缀名
        String suffixName = url.substring(url.lastIndexOf("."));
        //判断文件是否存在如果不存在就返回默认图片或者进行异常处理
        if (!(file.exists() && file.canRead())) {
            return Resp.success(false,"文件不存在！");
        }
        FileInputStream inputStream = null;
        OutputStream stream = null;
        try {
            inputStream = new FileInputStream(file);
//            byte[] data = new byte[(int) file.length()];
            response.setContentType("image/png;charset=utf-8");
            stream = response.getOutputStream();
            IOUtils.copy(inputStream,stream); // 将输入流的内容拷贝到输出流中
            stream.flush();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            try {
                stream.close();
                inputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }

        }
        return Resp.success(true,"成功！");
    }

}